﻿#建议保存编码为：bom头 + utf8
#Requires -RunAsAdministrator
# 本脚本由任务计划，每分钟拉起运行一次。
Start-Sleep -Seconds 1

${script:嬴政_ip} = '1.1.1.1'   # Master ip

#region 参数
${script:启用日志} = $true
#----------------------------------------
${script:嬴扶苏_太子已蹲东宫状态_检测太子心跳_间隔秒} = 5
${script:嬴扶苏_到太子探测皇帝是否存活状态前_检测太子心跳_次数} = 2
${script:嬴扶苏_太子已蹲东宫状态_产生太子心跳_间隔秒} = 11

#----------------------------------------
${script:嬴扶苏_太子探测皇帝是否存活状态_检测皇帝心跳_间隔秒} = 5
${script:嬴扶苏_篡位前_检测皇帝心跳_次数} = 2
${script:嬴扶苏_太子探测皇帝是否存活状态_产生皇帝心跳_间隔秒} = 11

#----------------------------------------
${script:嬴扶苏_太子已篡位状态_检测太子心跳_间隔秒} = 5
${script:嬴扶苏_太子已篡位状态_推送数据库_间隔秒} = 10
${script:嬴扶苏_太子已篡位状态_产生太子心跳_间隔秒} = 11

#endregion 参数

#region 函数

function 检测皇帝心跳
{
	& 'cdip.ps1' -被控机ip地址 ${script:嬴政_ip}
	$private:嬴政心跳 = & 'k_run_ip.ps1' -powershell代码块 {
		if (Test-Path -LiteralPath '/etc/kasini3000')
		{
			Test-Path -LiteralPath  '/etc/kasini3000/high_available/太子篡位邪念.txt'
		}

		if (Test-Path -LiteralPath 'c:\ProgramData\kasini3000\')
		{
			Test-Path -LiteralPath   'c:\ProgramData\kasini3000\high_available\太子篡位邪念.txt'
		}
	}

	if ($private:嬴政心跳 -is [array])
	{
		return $private:嬴政心跳[-1]
	}
	else
	{
		return $private:嬴政心跳
	}
}


function 产生皇帝心跳
{
	& 'cdip.ps1' -被控机ip地址 ${script:嬴政_ip}
	& 'k_run_ip.ps1' -powershell代码块 {
		if (Test-Path -LiteralPath '/etc/kasini3000')
		{
			New-Item -ItemType File -Force -Path '/etc/kasini3000/high_available/' -name '太子篡位邪念.txt'
		}

		if (Test-Path -LiteralPath 'c:\ProgramData\kasini3000\')
		{
			New-Item -ItemType File -Force -Path 'c:\ProgramData\kasini3000\high_available' -name '太子篡位邪念.txt'
		}
	}
}

function 检测太子心跳
{
	return $(Test-Path -LiteralPath "${global:kasini3000目录}/high_available/太子篡位邪念.txt")
}

function 产生太子心跳
{
	New-Item -ItemType File -Force -Path "${global:kasini3000目录}/high_available/" -name '太子篡位邪念.txt'
}


function 太子篡权_抢地主
{
	if ( ($IsWindows -eq $True) -or ($PSVersionTable.psversion.major -lt 6) ) #win
	{
		& 'u库定时任务_建立任务计划_win.ps1'
	}

	if ($IsLinux -eq $True)
	{
		& 'u库定时任务_建立任务计划_linux.ps1'
	}
}

function 太子让位_成农民
{
	if ( ($IsWindows -eq $True) -or ($PSVersionTable.psversion.major -lt 6) ) #win
	{
		& 'zkj_uninstall_k记饭店_win主控机.ps1'
	}

	if ($IsLinux -eq $True)
	{
		& 'zkj_uninstall_k记饭店_linux主控机.ps1'
	}

	& 'u_db_crontab_杀进程.ps1'
	& 'u库定时任务_线程级别_缓存进程_杀进程.ps1'
	& 'u库定时任务_进程级别_缓存进程_杀进程.ps1'

	& 'u库定时任务_线程级别_杀进程.ps1'
	& 'u库定时任务_进程级别_杀进程.ps1'
	Start-Sleep -Seconds 1
	推送master数据库
}

function 推送master数据库
{
	#Add-Content -LiteralPath "${global:kasini3000目录}/cmdb/d当前库/user_crontab.sqlite3" -Value ('' + (Get-Date -format F) + '备机')
	& 'cdip.ps1' -被控机ip地址 ${script:嬴政_ip}
	$private:linux版本字串 = 'centos8','centos7','centos6','debian8','debian9','debian10','ubuntu1404','ubuntu1604','ubuntu1804','centos8','alpine','ubuntu2004'
	$private:win版本字串 = 'win2008r2','win7','win8','win10','win2012r2','win2016','win2019'
	if ($global:当前被控机_ip.被控机os类型 -in $private:linux版本字串)
	{
		& 'k_copyto_ip.ps1' -LiteralPath "${global:kasini3000目录}/cmdb/d当前库/user_crontab.sqlite3" -Destination  '/etc/kasini3000/cmdb/d当前库/'
	}

	if ($global:当前被控机_ip.被控机os类型 -in $private:win版本字串)
	{
		& 'k_copyto_ip.ps1' -LiteralPath "${global:kasini3000目录}/cmdb/d当前库/user_crontab.sqlite3" -Destination  'c:\ProgramData\kasini3000\cmdb\d当前库'
	}
}

function 检测太子在位否
{
	if ( ($IsWindows -eq $True) -or ($PSVersionTable.psversion.major -lt 6) ) #win
	{
		return $(& 'u库定时任务_检查任务计划存在否_win.ps1')
	}

	if ($IsLinux -eq $True)
	{
		return $(& 'u库定时任务_检查任务计划存在否_linux.ps1')
	}
}

function 写日志($被写入的log内容)
{
	if (${script:启用日志} -eq $True)
	{
		$private:日志全路径 = "${global:kasini3000目录}/high_available/卡死你3000高可用日志备机.txt"
		$private:temp = Get-Item -LiteralPath $private:日志全路径
		if ($private:temp.Length -gt 128mb)
		{
			Remove-Item -Force -LiteralPath $private:日志全路径
		}
		$时间 = Get-Date -Format F
		$输出信息 = "$时间	$被写入的log内容"
		Add-Content -LiteralPath $private:日志全路径 -Value $输出信息 -Encoding UTF8
	}
}

function 写日志2($被写入的log内容)
{
	$private:日志全路径 = "${global:kasini3000目录}/high_available/卡死你3000高可用日志备机.txt"
	$private:temp = Get-Item -LiteralPath $private:日志全路径
	if ($private:temp.Length -gt 128mb)
	{
		Remove-Item -Force -LiteralPath $private:日志全路径
	}
	$时间 = Get-Date -Format F
	$输出信息 = "$时间	$被写入的log内容"
	Add-Content -LiteralPath $private:日志全路径 -Value $输出信息 -Encoding UTF8
}


#endregion 函数

#-------------------main--------------------
if ( ($IsWindows -eq $True) -or ($PSVersionTable.psversion.major -lt 6) ) #win
{
	& 'c:\ProgramData\kasini3000\0k_source.ps1'
}

if ($IsLinux -eq $True)
{
	& '/etc/kasini3000/0k_source.ps1'
}

$private:win = 'win7','win8','win10','win2008r2','win2012r2','win2016','win2019'
$private:linux = 'centos7','centos8','debian8','debian9','debian10','ubuntu1404','ubuntu1604','ubuntu1804','alpine'
$private:all = $win + $linux
& 'cdip.ps1' -被控机ip地址 ${script:嬴政_ip}
if (($LASTEXITCODE -ne 0) -or ($global:当前被控机_ip.被控机os类型 -notin $private:all))
{
	写日志 '错误：找不到被控机【嬴政】，退出码11'
	exit 11
}

$private:standby磁盘文件 = "${global:kasini3000目录}/high_available/standby_pid.txt"
if (Test-Path -LiteralPath $private:standby磁盘文件)
{
	$private:旧standby_pid = Get-Content -LiteralPath $private:standby磁盘文件
}

if ( ($private:旧standby_pid -eq $null) -or ($private:旧standby_pid -eq '') )
{

}
else
{
	$private:旧standby进程 = Get-Process -id $private:旧standby_pid
}

if ($private:旧standby进程 -eq $null)
{

}
else
{
	if ( ($private:旧standby进程.ProcessName -eq 'pwsh') -or ($private:旧standby进程.ProcessName -eq 'powershell') )
	{
		写日志 "错误：旧的standby进程，还在运行中！【$private:旧standby_pid】它将被替换成新的。"
		Stop-Process -Force -id $private:旧standby_pid
	}
}
Set-Content -LiteralPath $private:standby磁盘文件 -Value $pid -Encoding UTF8 -Force
写日志 "新pid： $pid"

while ((Get-Date).Second -lt 55)
{
	${script:现在} = Get-Date

	switch (${script:嬴扶苏状态})
	{
		'太子将失位'
		{
			写日志2 '太子将失位'
			太子让位_成农民
			写日志2 '太子已失位'

			写日志 '开始推送master数据库4'
			推送master数据库

			写日志 '开始建立皇帝心跳5'
			产生皇帝心跳

			${script:嬴扶苏状态} = '太子已蹲东宫'
			break
		}

		'太子已篡位'
		{
			写日志 '太子已篡位'
			if (${script:现在} -gt ${script:嬴扶苏_太子已篡位状态_建立太子心跳_超时})
			{
				${script:嬴扶苏_太子已篡位状态_建立太子心跳_超时} = ${script:现在}.AddSeconds(${script:嬴扶苏_太子已篡位状态_产生太子心跳_间隔秒})
				写日志 "太子已经篡位1，开始建立太子心跳"
				产生太子心跳
			}

			if (${script:现在} -gt ${script:嬴扶苏_太子已篡位状态_检测太子心跳_超时})
			{
				${script:嬴扶苏_太子已篡位状态_检测太子心跳_超时} = ${script:现在}.AddSeconds(${script:嬴扶苏_太子已篡位状态_检测太子心跳_间隔秒})
				写日志 "太子已经篡位2，开始检测太子心跳"
				$private:检测太子心跳结果 = 检测太子心跳
				if ($private:检测太子心跳结果 -eq $true)
				{
					写日志 '太子已篡位3，有太子心跳'
				}
				else
				{
					写日志 '太子已篡位3，无太子心跳'
					${script:嬴扶苏状态} = '太子将失位'
					${script:嬴扶苏_太子已篡位状态_产生太子心跳_间隔秒} = $null
					${script:嬴扶苏_太子已篡位状态_检测太子心跳_间隔秒} = $null
					${script:嬴扶苏_太子已篡位状态_推送数据库_超时} = $null
				}
			}

			break
		}

		'太子将篡位'
		{
			写日志2 '太子将篡位'
			太子篡权_抢地主
			写日志2 '太子已篡位'
			${script:嬴扶苏状态} = '太子已篡位'
			break
		}

		'太子探测皇帝是否存活'
		{
			写日志 '太子探测皇帝是否存活开始'
			if (${script:现在} -gt ${script:嬴扶苏_太子探测皇帝是否存活状态_产生皇帝心跳_超时})
			{
				${script:嬴扶苏_太子探测皇帝是否存活状态_产生皇帝心跳_超时} = ${script:现在}.AddSeconds(${script:嬴扶苏_太子探测皇帝是否存活状态_产生皇帝心跳_间隔秒})
				写日志 '太子探测皇帝是否存活1，开始建立皇帝心跳'
				产生皇帝心跳
			}

			if (${script:现在} -gt ${script:嬴扶苏_太子探测皇帝是否存活状态_检测皇帝心跳_超时})
			{
				${script:嬴扶苏_太子探测皇帝是否存活状态_检测皇帝心跳_超时} = ${script:现在}.AddSeconds(${script:嬴扶苏_太子探测皇帝是否存活状态_检测皇帝心跳_间隔秒})

				写日志 '太子探测皇帝是否存活2，开始检测皇帝心跳'
				$private:检测皇帝心跳结果 = 检测皇帝心跳
				if ($private:检测皇帝心跳结果 -eq $true)
				{
					写日志 '太子探测皇帝是否存活2，有皇帝心跳'
					${script:嬴扶苏状态} = '太子已蹲东宫'
					${script:嬴扶苏_太子探测皇帝是否存活状态_产生皇帝心跳_间隔秒} = $null
					${script:嬴扶苏_太子探测皇帝是否存活状态_检测皇帝心跳_间隔秒} = $null
					$private:无皇帝心跳次数 = 0
				}
				else
				{
					写日志 '太子探测皇帝是否存活2，无皇帝心跳'
					$private:无皇帝心跳次数++
					if ($private:无皇帝心跳次数 -gt ${script:嬴扶苏_篡位前_检测皇帝心跳_次数})
					{
						${script:嬴扶苏状态} = '太子将篡位'
						${script:嬴扶苏_太子探测皇帝是否存活状态_产生皇帝心跳_间隔秒} = $null
						${script:嬴扶苏_太子探测皇帝是否存活状态_检测皇帝心跳_间隔秒} = $null
						$private:无皇帝心跳次数 = 0
					}
				}

				break
			}
		}

		'太子已蹲东宫'
		{
			写日志 '太子已蹲东宫'
			if (${script:现在} -gt ${script:嬴扶苏_太子已蹲东宫状态_产生太子心跳_超时})
			{
				${script:嬴扶苏_太子已蹲东宫状态_产生太子心跳_超时} = ${script:现在}.AddSeconds(${script:嬴扶苏_太子已蹲东宫状态_产生太子心跳_间隔秒})
				写日志 '太子已蹲东宫1，产生太子心跳'
				产生太子心跳
			}

			if (${script:现在} -gt ${script:嬴扶苏_太子已蹲东宫状态_检测太子心跳_超时})
			{
				${script:嬴扶苏_太子已蹲东宫状态_检测太子心跳_超时} = ${script:现在}.AddSeconds(${script:嬴扶苏_太子已蹲东宫状态_检测太子心跳_间隔秒})
				if (检测太子心跳)
				{
					写日志 '太子已蹲东宫2，有太子心跳'
					$private:太子心跳次数++
					if ($private:太子心跳次数 -gt ${script:嬴扶苏_到太子探测皇帝是否存活状态前_检测太子心跳_次数} )
					{
						${script:嬴扶苏状态} = '太子探测皇帝是否存活'
						${script:嬴扶苏_太子已蹲东宫状态_产生太子心跳_超时} = $null
						${script:嬴扶苏_太子已蹲东宫状态_检测太子心跳_超时} = $null
						$private:太子心跳次数 = 0
					}
				}
				else
				{
					写日志 '太子已蹲东宫2，无太子心跳'
					$private:太子心跳次数 = 0
				}
			}

			break
		}

		default
		{
			#main2
			写日志 '卡死你3000主控机高可用，备机，脚本开始'
			if (检测太子在位否)
			{
				${script:嬴扶苏状态} = '太子已篡位'
			}
			else
			{
				${script:嬴扶苏状态} = '太子已蹲东宫'
			}
		}
	}
	Start-Sleep -Seconds 1
}

写日志 '卡死你3000主控机高可用，备机，脚本结束'
exit 0
